package com.ltmonitor.web.controller;

import java.io.Console;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.ltmonitor.entity.Department;
import com.ltmonitor.entity.GPSRealData;
import com.ltmonitor.service.IDepartmentService;
import com.ltmonitor.service.IRealDataService;
import com.ltmonitor.util.Constants;
import com.ltmonitor.util.DateUtil;
import com.ltmonitor.util.StringUtil;
import com.ltmonitor.web.util.OnlineUser;
import com.ltmonitor.web.util.OnlineUserStatistic;
import com.ltmonitor.web.vo.VehicleTreeNode;
import com.ltmonitor.web.vo.VehicleTreeResult;

/**
 * 车辆树 用于查询部门和车辆数据，并形式树状数据结构，输出JSON格式到前台页面 树的JSON格式参考:easyui的手册
 * 
 * @author DELL
 * 
 */
@Controller
public class VehicleTreeAction extends GenericAction {

	@Autowired
	private IRealDataService realDataService;

	/**
	 * 生成车辆树菜单
	 * 
	 * @param updateNode
	 *            前台刷新车辆数的标志，表示是更新节点的状态，而不是创建
	 * @param filter
	 *            是否是过滤模式，如果是过滤模式，则默认节点全部打开，否则节点是收缩延迟加载的模式
	 * @return
	 */
	@RequestMapping("/vehicle/getVechecileTree.action")
	@ResponseBody
	public VehicleTreeResult getVehicleTree(boolean updateNode, boolean filter) {
			
		
		Date start = new Date();
		// log.error("开始查询树");
		VehicleTreeResult treeResult = new VehicleTreeResult();
		Map<String, VehicleTreeNode> treeNodeMap = new HashMap<String, VehicleTreeNode>();

		ArrayList<VehicleTreeNode> treeData = treeResult.getTreeData();// new
																		// ArrayList<VehicleTreeNode>();
		// 生成车辆树
		try {
			OnlineUser user = getOnlineUser();
			if (user == null) {
				log.error("session 失效，没有获取到当前登录用户数据");
				treeResult.setError("SessionInvalid");
				return treeResult;
			}
			// 用户分配的车队

			Date start2 = new Date();
			List<Department> depList = getAuthorizedDepList(updateNode,
					treeNodeMap);

			Date endDate2 = new Date();
			if (updateNode == false) {
				double min2 = DateUtil.getSeconds(start2, endDate2);
				//log.error("查询部门节点耗时:" + min2 + "秒");
			}

			if (depList == null) {
				log.error("session 失效，没有获取到部门数据");
				return treeResult;
			}
			for (Department dep : depList) {
				setTreeData(dep, treeNodeMap);
			}
			Date start1 = new Date();
			createVehicleTreeNode(updateNode, treeNodeMap, treeResult);// 创建车辆树节点

			if (updateNode == false) {
				Date endDate1 = new Date();
				double min1 = DateUtil.getSeconds(start1, endDate1);
				//log.error("创建车辆节点耗时:" + min1 + "秒");
			}

			int totalNum = 0;
			int onlineNum = 0;
			for (Department dep : depList) {
				String childNodeId = "dep" + dep.getEntityId();
				VehicleTreeNode node = treeNodeMap.get(childNodeId);
				if (node == null || node.getTotalNum() == 0)
					continue;

				String parentNodeId = "dep" + dep.getParentId();
				VehicleTreeNode parentNode = treeNodeMap.get(parentNodeId);
				if (parentNode != null) {
					parentNode.getChildren().add(node);
				} else if (updateNode == false) {
					node.setState("open");
					treeData.add(node);
					totalNum += node.getTotalNum();
					onlineNum += node.getOnlineNum();
				}

				String nodeText = dep.getName() + "(" + node.getOnlineNum()
						+ "/" + node.getTotalNum() + ")";
				node.setName(nodeText);

				if (filter) {
					// 过滤模式下，默认展开所有节点
					node.setState("open");
				}

				if (updateNode) {
					if (needRefresh(node)) {
						treeData.add(node);
					}
				}
			}
			/**
			 * if (treeData.size() > 1) { VehicleTreeNode vn = new
			 * VehicleTreeNode(); vn.setOnlineNum(onlineNum);
			 * vn.setTotalNum(totalNum); vn.setName("监控平台" + "(" +
			 * vn.getOnlineNum() + "/" + vn.getTotalNum() + ")"); }
			 */

		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
			ex.printStackTrace();//输出错误
		}

		if (treeData.size() == 0 && updateNode == false) {
			VehicleTreeNode mzTn = new VehicleTreeNode("1",
					"<font color='red'>没有查询到车辆</font>", "0");
			mzTn.setIconSkin("department");
			treeData.add(mzTn);
		}

		if (updateNode == false) {
			Date endDate = new Date();

			double min = DateUtil.getSeconds(start, endDate);
			//log.error("查询树耗时:" + min + "秒");
		}

		// 统计上线车辆数和上线率,显示在前台
		// 更新用户的在线时间
		OnlineUserStatistic.UpdateOnlineTime(getOnlineUser().getEntityId());
		// 得到在线用户数
		int onlineUserNum = OnlineUserStatistic.getOnlineUserNum();

		treeResult.setOnlineUserNum(onlineUserNum);
		//log.error("返回更新结果:"+ treeResult.getTreeData().size());
		return treeResult;
	}

	private List<Department> getAuthorizedDepList(boolean updateNode,
			Map<String, VehicleTreeNode> treeNodeMap) {
		List<Department> depList = null;
		if (updateNode) {
			// 如果是更新模式，则只需要从session中读取
			depList = (List) getFromSession("depListForTree");
			return depList;
		}
		List<Long> depIdList = getOnlineUser().getDepIdList();
		Map<Long, Long> depIdMap = new HashMap<Long, Long>();
		depList = departmentService.fetchDepartmentList(depIdList);
		for (Department dep : depList) {
			if (dep == null || depIdMap.containsKey(dep.getEntityId())
					|| dep.getDeleted())
				continue;
			if (depIdMap.containsKey(dep.getEntityId()) == false) {
				setTreeData(dep, treeNodeMap);
				depIdMap.put(dep.getEntityId(), dep.getEntityId());
			}

		}
		Collections.sort(depList, new Comparator<Department>() {
			@Override
			public int compare(Department o1, Department o2) {
				if (o1.getName() == null)
					return -1;

				return o1.getName().compareTo(o2.getName());
			}

		});
		putSession("depListForTree", depList);
		return depList;
	}

	/**
	 * 根据用户权限，查询所分配的车辆，返回车辆列表，并缓存在Session中 首次查询数据库，以后就从session中获取
	 * 
	 * @return
	 */
	private List queryVehicleTree(boolean updateNode) {
		List result = null;
		if (updateNode) {
			result = (List) getFromSession("vehicleTree");
		}

		if (result == null) {
			Date start = new Date();
			String queryId = "vehicle.selectVehicleTree";
			Map params = super.getParams();
			params.put("userId", getOnlineUser().getEntityId());
			result = queryService.query(queryId, params);
			putSession("vehicleTree", result);
		}

		if (result == null)
			result = new ArrayList();

		return result;
	}

	/**
	 * 创建车辆树节点
	 */
	private void createVehicleTreeNode(boolean updateNode,
			Map<String, VehicleTreeNode> treeNodeMap,
			VehicleTreeResult treeResult) {
		// List result = queryVehicleTree();
		// IRealDataService realService = getRealDataService();

		try {
			
		
		int onlineNum = 0;
		int totalNum = 0;
		// 处于停车状态的车辆数目
		int parkingNum = 0;

		Map<String, GPSRealData> realMap = new HashMap<String, GPSRealData>();
		List<VehicleTreeNode> vehicleTreeNodes = (List<VehicleTreeNode>) this
				.getFromSession("vehicleTree");
		if (updateNode == false || vehicleTreeNodes == null) {
			vehicleTreeNodes = new ArrayList<VehicleTreeNode>();
			String queryId = "vehicle.selectVehicleTree";
			Map params = super.getParams();
			params.put("userId", getOnlineUser().getEntityId());
			List<Map<String, Object>> result = queryService.query(queryId,
					params);

			Map<Long, Long> nodeMap = new HashMap<Long, Long>();
			int m = 0;
			boolean hasVideoAuthority = hasRealTimeVideoAuthority();
			for (Map rowData : result) {
				String plateNo = "" + rowData.get("plateNo");
				String simNo = "" + rowData.get("simNo");
				// String driverName = "" + rowData.get("driverName");
				long vehicleId = (Integer) rowData.get("vehicleId");
				int videoChannelNum = (Integer) rowData.get("videoChannelNum");
				long depId = (Integer) rowData.get("depId");
				double velocity = 0;
				boolean online = false;
				String acc = "0";
				//log.error("before get:" + simNo);
				String nodeDescr = plateNo + "&nbsp;&nbsp;&nbsp;";

				String icon = "offlinecar"; // 离线图标

				GPSRealData rd = getRealDataService().get(simNo);
				//log.error((m++)+"get:" + simNo );
					if (rd != null) {
						online = rd.getOnline();
						velocity = rd.getVelocity();
						String status = rd.getStatus();
						acc = status.substring(31, 32);

						// 通过阿里获取地址描述信息
//					GetLocation gl = new GetLocation();
//					if(rd.getLongitude() >0 && rd.getLatitude() >0){
//						nodeDescr += "("+gl.getCity(rd.getLongitude()+"",rd.getLatitude()+"")+")";
//					}

						if (online) {
							onlineNum++;
							if (acc.equals("1")) {
								if (rd.getAlarmState() != null && rd.getAlarmState().indexOf("1") >= 0) {
									if (velocity > 0) {
										icon = "drivecarAlarm"; // ACC开行驶报警图标
										// nodeDescr += "行驶报警" + (int) velocity;
									} else {
										if (rd != null && rd.getParkingTime() != null) {
											double parkingTime = 0.1
													* DateUtil.getSeconds(rd.getParkingTime(), new Date()) / 6;
											// nodeDescr += "停车报警"
											// + Constants.getIntervalDescr(parkingTime);
										}

										parkingNum++;
										icon = "parkingcarAlarm";// ACC开停车报警图标
									}
								} else {
									if (velocity > 0) {
										icon = "drivecar"; // ACC开行驶图标
										// nodeDescr += "行驶" + (int) velocity;
									} else {
										if (rd != null && rd.getParkingTime() != null) {
											double parkingTime = 0.1
													* DateUtil.getSeconds(rd.getParkingTime(), new Date()) / 6;
											// nodeDescr += "ACC开停车"
											// + Constants.getIntervalDescr(parkingTime);
										}

										parkingNum++;
										icon = "parkingcar";// ACC开停车图标
									}
								}
							} else {
								parkingNum++;
								if (rd.getAlarmState() != null && rd.getAlarmState().indexOf("1") >= 0) {
									icon = "accoffAlarm";// ACC关停车报警图标
									// nodeDescr += "ACC关报警";
								} else {
									icon = "accoffPacking";// ACC关停车图标
									// nodeDescr += "ACC关停车";
								}
							}
							if (rd.IsValid() == false) {
								icon = "onlineInValid";// 在线无效定位图标
							}
						} else {
							if (rd.IsValid() == false && rd.getSendTime() != null) {
								icon = "offlineInValid";// 离线无效定位图标
							}
						} // end online
					} // end rd

				String tid = "v" + vehicleId;
				String parentNodeId = "dep" + depId;
				VehicleTreeNode vn = new VehicleTreeNode(tid, nodeDescr,
						parentNodeId, icon);
				
				/*
				 * author:shinion
				 * date:2019-01-11
				 * 添加功能，通过节点的属性成员，携带实时数据基本信息
				 * 		携带数据：
				 * 				1.报警状态信息
				 * 				2.地址信息
				 * 
				 * */
				if(rd != null) {
					vn.getAttributes().put("flg", "初始化");
					vn.getAttributes().put("alarmStatus", rd.getAlarmState());
					vn.getAttributes().put("location", rd.getLocation());
					vn.getAttributes().put("online", rd.getOnline());
					vn.getAttributes().put("valid", rd.IsValid());
				}		
				
				
				
				
				///////////////
				//添加功能结束
				
				vehicleTreeNodes.add(vn);
				//vn.setChildren(null);
				// mzTn.setLeaf(true);
				vn.setSimNo(simNo);
				//vn.setState("open");
				vn.getAttributes().put("plateNo", plateNo);
				if (nodeMap.containsKey(vehicleId) == false) {
					nodeMap.put(vehicleId, vehicleId);
					VehicleTreeNode parentNode = treeNodeMap.get(parentNodeId);
					if (parentNode != null) {
						parentNode.getChildren().add(vn);

						if(hasVideoAuthority) {
							for (int ch = 1; ch <= videoChannelNum; ch++) {
								String chNodeId = "ch" + vehicleId + "_" + ch;
								String chIcon = "camera";
								VehicleTreeNode chNode = new VehicleTreeNode(chNodeId, "通道" + ch,
										tid, chIcon);
								chNode.setChildren(null);
								//chNode.setl true;
								chNode.setNocheck(true);
								//chNode.state = "open";
								if (vn.getChildren() == null)
									vn.setChildren(new ArrayList<VehicleTreeNode>());
								vn.getChildren().add(chNode);
							}
						}
					}
				}

				VehicleTreeNode depNode = treeNodeMap.get(parentNodeId);
				while (depNode != null) {
					depNode.setTotalNum(depNode.getTotalNum() + 1);
					if (online)
						depNode.setOnlineNum(depNode.getOnlineNum() + 1);
					parentNodeId = depNode.getPid();
					depNode = treeNodeMap.get(parentNodeId);
				}
				//log.error("end loop:" + simNo);
			}
			putSession("vehicleTree", vehicleTreeNodes);
		} else {
			for (VehicleTreeNode tn : vehicleTreeNodes) {
				String nodeDescr = tn.getAttributes().get("plateNo")
						+ "&nbsp;&nbsp;&nbsp;";
				boolean online = false;
				String icon = "offlinecar"; // 离线图标
				if (getRealDataService() != null) {
					GPSRealData rd = getRealDataService().get(tn.getSimNo());
					double velocity = 0;
					String acc = "0";
					if (rd != null) {
						online = rd.getOnline();
						velocity = rd.getVelocity();
						String status = rd.getStatus();
						acc = status.substring(31, 32);
						//通过阿里获取地址描述信息
//						GetLocation gl = new GetLocation();
//						if(rd.getLongitude() >0 && rd.getLatitude() >0){
//							nodeDescr += "("+gl.getCity(rd.getLongitude()+"",rd.getLatitude()+"")+")";
//						}
					} else
						online = false;
					/*if (online) {
						onlineNum++;
						if (velocity > 1) {
							icon = "onlinecar"; // 运行图标
							nodeDescr += "行驶" + (int) velocity;
						} else {
							if (rd != null && rd.getParkingTime() != null) {
								double parkingTime = 0.1 * DateUtil.getSeconds(
										rd.getParkingTime(), new Date()) / 6;
								nodeDescr += "停车"
										+ Constants
												.getIntervalDescr(parkingTime);
							}

							parkingNum++;
							icon = "parkingcar";// 停车图标
						}
					} else {
						nodeDescr += "离线";
					}*/
					if(rd != null) {
						
					
					if (online) {
						onlineNum++;
						if(acc.equals("1")){
							if(rd.getAlarmState() != null && rd.getAlarmState().indexOf("1") >= 0){
								if (velocity > 0) {
									icon = "drivecarAlarm"; // ACC开行驶报警图标
									//nodeDescr += "行驶报警" + (int) velocity;
								} else {
									if (rd != null && rd.getParkingTime() != null) {
										double parkingTime = 0.1 * DateUtil.getSeconds(
												rd.getParkingTime(), new Date()) / 6;							
										//nodeDescr += "停车报警"
										//		+ Constants.getIntervalDescr(parkingTime);
									}

									parkingNum++;
									icon = "parkingcarAlarm";// ACC开停车报警图标
								}
							}else{
								if (velocity > 0) {
									icon = "drivecar"; // ACC开行驶图标
									//nodeDescr += "行驶" + (int) velocity;
								} else {
									if (rd != null && rd.getParkingTime() != null) {
										double parkingTime = 0.1 * DateUtil.getSeconds(
												rd.getParkingTime(), new Date()) / 6;
										//nodeDescr += "ACC开停车"
										//		+ Constants.getIntervalDescr(parkingTime);
									}

									parkingNum++;
									icon = "parkingcar";// ACC开停车图标
								}
							}
						}else{
							parkingNum++;
							if(rd.getAlarmState() != null && rd.getAlarmState().indexOf("1") >= 0){
								icon = "accoffAlarm";// ACC关停车报警图标	
								//nodeDescr += "ACC关报警";
							}else{
								icon = "accoffPacking";// ACC关停车图标
								//nodeDescr += "ACC关停车";
							}	
						}
						if (rd.IsValid()==false){
							icon = "onlineInValid";// 在线无效定位图标	
						}
					} else{
						if (rd.IsValid()==false  && rd.getSendTime() != null){
							icon = "offlineInValid";// 离线线无效定位图标	
						}
					}
					
					
					/*
					 * 添加属性值
					 * */
					tn.getAttributes().put("flg", "更新");
					tn.getAttributes().put("alarmStatus", rd.getAlarmState());
					tn.getAttributes().put("location", rd.getLocation());
					tn.getAttributes().put("online", rd.getOnline());
					tn.getAttributes().put("valid", rd.IsValid());
					}//end rd
	
				}				

				if (icon.equals(tn.getIconSkin()) == false
						|| nodeDescr.equals(tn.getName()) == false) {
					tn.setIconSkin(icon);
					tn.setName(nodeDescr);
					treeResult.getTreeData().add(tn);
				}

				String parentNodeId = tn.getPid();
				VehicleTreeNode depNode = treeNodeMap.get(parentNodeId);
				while (depNode != null) {
					depNode.setTotalNum(depNode.getTotalNum() + 1);
					if (online)
						depNode.setOnlineNum(depNode.getOnlineNum() + 1);
					parentNodeId = depNode.getPid();
					depNode = treeNodeMap.get(parentNodeId);
				}

			}
		}

		totalNum = vehicleTreeNodes.size();
		int offlineNum = totalNum - onlineNum;
		treeResult.setOfflineNum(offlineNum);
		treeResult.setOnlineNum(onlineNum);
		treeResult.setTotalNum(totalNum);
		treeResult.setParkingNum(parkingNum);
		double onlineRate = 0;
		if (totalNum > 0 && onlineNum > 0)
			onlineRate = 100.00 * onlineNum / totalNum;
		String strOnlineRate = null;
		if (onlineRate > 0) {
			DecimalFormat df = new DecimalFormat("######0.00");
			strOnlineRate = df.format(onlineRate);
		} else
			strOnlineRate = "0";

		treeResult.setOnlineRate(strOnlineRate);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

	/**
	 * 判断部门节点是否需要刷新 由于部门节点名称是大连物流中心(12/24)的形式 依据是部门的在线车辆数和总数发生变化的时候，节点的名称也会变化,
	 * 此时就需要更新前端的节点
	 * 
	 * @param tn
	 *            部门节点
	 * @return
	 */
	private boolean needRefresh(VehicleTreeNode tn) {
		String SESSION_FOR_TREE_NODE_MAP = "DepTreeNodeMap";
		Map<String, String> nodeMap = (Map<String, String>) this
				.getFromSession(SESSION_FOR_TREE_NODE_MAP);
		if (nodeMap == null) {
			nodeMap = new HashMap<String, String>();
			nodeMap.put(tn.getId(), tn.getName());
			putSession(SESSION_FOR_TREE_NODE_MAP, nodeMap);

			return true;
		}
		String oldTn = nodeMap.get(tn.getId());
		if (oldTn == null) {
			nodeMap.put(tn.getId(), tn.getName());
			return true;
		}

		if (oldTn.equals(tn.getName())) {
			return false;
		}
		nodeMap.put(tn.getId(), tn.getName());
		return true;
	}

	private void setTreeData(Department dep,
			Map<String, VehicleTreeNode> treeNodeMap) {
		try {
			String depNodeId = "dep" + dep.getEntityId();
			long parentId = dep.getParentId();
			// parentId = parentId > 0 ? ("dep_"+parentId) : 1;
			String strParentNodeId = "dep" + parentId;
			if (parentId == 0) {
				strParentNodeId = "1";
			}

			VehicleTreeNode depNode = new VehicleTreeNode(depNodeId,
					dep.getName(), strParentNodeId);

			depNode.setIconSkin("department");
			treeNodeMap.put(depNode.getId(), depNode);

		} catch (Exception ex) {
			log.error(ex.getMessage(), ex);
		}
	}

	public IRealDataService getRealDataService() {
		return realDataService;
	}

	public void setRealDataService(IRealDataService realDataService) {
		this.realDataService = realDataService;
	}

}
